// fork get-port
const os = require('os');
const net = require('net');
const { name: pkgName } = require('../package.json')
const port = <%= port %>;

async function checkPortIsOccupied() {
  const hosts = getLocalHosts();

  for (const host of hosts) {
    try {
      await checkAvailablePort({ port, host }); // eslint-disable-line no-await-in-loop
    } catch (error) {
      if (!['EADDRNOTAVAIL', 'EINVAL'].includes(error.code)) {
        throw error;
      }
    }
  }
}

(async function(){
  try{
    await checkPortIsOccupied()
  }catch(e){
    console.warn(`\u001b[33m In [ ${pkgName} ] application, port [ ${port} ]  is occupied. Check whether other services are started! \u001b[39m\n`);

    console.log(
      `\u001b[33m If you want to replace the item port, manually update the sub-application information registered in the main application. Otherwise, [qiankun] fails to obtain resources. \u001b[39m\n`,
    );
    process.exit(1);
  }
})()



function checkAvailablePort(options) {
  return new Promise((resolve, reject) => {
    const server = net.createServer();
    server.unref();
    server.on('error', reject);

    server.listen(options, () => {
      const { port } = server.address();
      server.close(() => {
        resolve(port);
      });
    });
  });
}

function getLocalHosts() {
  const interfaces = os.networkInterfaces();

  // Add undefined value for createServer function to use default host,
  // and default IPv4 host in case createServer defaults to IPv6.
  const results = new Set([undefined, '0.0.0.0']);

  for (const _interface of Object.values(interfaces)) {
    for (const config of _interface) {
      results.add(config.address);
    }
  }

  return results;
}
